package hu.mapro.gwtui.gxt.client.fieldseditor.field;

import hu.mapro.gwtui.gxt.client.fieldseditor.FieldCreationInterface;
import hu.mapro.model.Getter;
import hu.mapro.model.Setter;

import com.google.common.base.Objects;
import com.google.gwt.editor.client.EditorDelegate;
import com.google.gwt.user.client.ui.Widget;
import com.sencha.gxt.widget.core.client.form.AdapterField;
import com.sencha.gxt.widget.core.client.form.ValueBaseField;

public class Util {

	public static <V> EditorFieldInterface<V> createValueEditorField(
			final ValueBaseField<V> editorField
	) {
		return new EditorFieldInterface<V>() {

			private Object baseObject;
			private V originalValue;
			private EditorDelegate<V> delegate;
			@SuppressWarnings("rawtypes")
			Setter setter;

			@SuppressWarnings("unchecked")
			@Override
			public void flush() {
				editorField.flush();
				V currentValue = editorField.getCurrentValue();
				setter.set(baseObject, currentValue);
				delegate.setDirty(!Objects.equal(originalValue, currentValue));
			}

			@Override
			public void setDelegate(EditorDelegate<V> delegate) {
				this.delegate = delegate;
				editorField.setDelegate(delegate);
			}

			@Override
			public Widget asWidget() {
				return editorField;
			}

			@Override
			public void focus() {
				editorField.focus();
			}

			@Override
			public void checkDirty() {
				editorField.getElement().blur();
				delegate.setDirty(!Objects.equal(editorField.getCurrentValue(), originalValue));
			}

			@Override
			public void setContext(FieldCreationInterface ctx) {
			}

			@Override
			public <T, A extends Getter<T, V> & Setter<T, V>> void edit(
					A accessor, T baseObject) {
				setter = accessor;
				this.baseObject = baseObject;
				originalValue = accessor.get(baseObject);
				editorField.setValue(originalValue);
				editorField.clearInvalid();
			}

		};
	}
	
	public static <V> EditorFieldInterface<V> createValueEditorField(
			final AdapterField<V> editorField
			) {
		return new EditorFieldInterface<V>() {
			
			private Object baseObject;
			private V originalValue;
			private EditorDelegate<V> delegate;
			@SuppressWarnings("rawtypes")
			Setter setter;
			
			@SuppressWarnings("unchecked")
			@Override
			public void flush() {
				V currentValue = editorField.getValue();
				setter.set(baseObject, currentValue);
				delegate.setDirty(!Objects.equal(originalValue, currentValue));
			}
			
			@Override
			public void setDelegate(EditorDelegate<V> delegate) {
				this.delegate = delegate;
				editorField.setDelegate(delegate);
			}
			
			@Override
			public Widget asWidget() {
				return editorField;
			}
			
			@Override
			public void focus() {
				editorField.focus();
			}
			
			@Override
			public void checkDirty() {
				editorField.getElement().blur();
				delegate.setDirty(!Objects.equal(editorField.getValue(), originalValue));
			}
			
			@Override
			public void setContext(FieldCreationInterface ctx) {
			}
			
			@Override
			public <T, A extends Getter<T, V> & Setter<T, V>> void edit(
					A accessor, T baseObject) {
				setter = accessor;
				this.baseObject = baseObject;
				originalValue = accessor.get(baseObject);
				editorField.setValue(originalValue);
				editorField.clearInvalid();
			}
			
		};
	}

	
	public static <V> EditorFieldInterface<V> create(
			final FieldInterface<V> editorField
	) {
		return new EditorFieldInterface<V>() {
			
			private Object baseObject;
			private V originalValue;
			private EditorDelegate<V> delegate;
			@SuppressWarnings("rawtypes")
			Setter setter;
			
			@SuppressWarnings("unchecked")
			@Override
			public void flush() {
				V currentValue = editorField.getValue();
				setter.set(baseObject, currentValue);
				delegate.setDirty(!Objects.equal(originalValue, currentValue));
			}
			
			@Override
			public void setDelegate(EditorDelegate<V> delegate) {
				this.delegate = delegate;
				editorField.setDelegate(delegate);
			}
			
			@Override
			public Widget asWidget() {
				return editorField.getWidget();
			}
			
			@Override
			public void focus() {
				editorField.focus();
			}
			
			@Override
			public void checkDirty() {
				editorField.blur();
				delegate.setDirty(!Objects.equal(editorField.getValue(), originalValue));
			}
			
			@Override
			public void setContext(FieldCreationInterface ctx) {
				editorField.setContext(ctx);
			}
			
			@Override
			public <T, A extends Getter<T, V> & Setter<T, V>> void edit(
					A accessor, T baseObject) {
				setter = accessor;
				this.baseObject = baseObject;
				originalValue = accessor.get(baseObject);
				editorField.setValue(originalValue);
				editorField.clearInvalid();
			}
			
		};
	}
	
	
//	public static <T, V, F extends Field&Getter<? super T, V>&Setter<? super T, V>&HasLabel> EditorFieldOperations<T, V> createValueEditorField(
//			final F field,
//			final ValueBaseField<V> editorField
//	) {
//		return new EditorFieldOperations<T, V>() {
//
//			private T baseObject;
//			private V originalValue;
//			private EditorDelegate<V> delegate;
//
//			@Override
//			public void flush() {
//				editorField.flush();
//				V currentValue = editorField.getCurrentValue();
//				field.set(baseObject, currentValue);
//				delegate.setDirty(!Objects.equal(originalValue, currentValue));
//			}
//
//			@Override
//			public void setDelegate(EditorDelegate<V> delegate) {
//				this.delegate = delegate;
//				editorField.setDelegate(delegate);
//			}
//
//			@Override
//			public Widget asWidget() {
//				return editorField;
//			}
//
//			@Override
//			public void focus() {
//				editorField.focus();
//			}
//
//			@Override
//			public void edit(T baseObject) {
//				this.baseObject = baseObject;
//				originalValue = field.get(baseObject);
//				editorField.setValue(originalValue);
//				editorField.clearInvalid();
//			}
//
//			@Override
//			public void checkDirty() {
//				editorField.getElement().blur();
//				delegate.setDirty(!Objects.equal(editorField.getCurrentValue(), originalValue));
//			}
//
//			@Override
//			public void setContext(FieldCreationContext ctx) {
//			}
//
//			@Override
//			public String getPropertyName() {
//				return field.getName();
//			}
//
//			@Override
//			public String getLabel() {
//				return field.getLabel();
//			}
//
//			@Override
//			public V getValue(T object) {
//				return field.get(object);
//			}
//		};
//	}

}
